home *** CD-ROM | disk | FTP | other *** search
/ Risc World 3 / Risc World 3.iso / SOFTWARE / ISSUE2 / PD / VINCE / !ViNCe / c / hex_enc < prev    next >
Text File  |  2002-03-10  |  11KB  |  345 lines

  1. /*
  2.  * hextile.c
  3.  *
  4.  * Routines to implement Hextile Encoding
  5.  */
  6.  
  7. /*
  8.  *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
  9.  *
  10.  *  This is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This software is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this software; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
  23.  *  USA.
  24.  */
  25.  
  26. #include <stdio.h>
  27. #include "rfb.h"
  28.  
  29. static Bool sendHextiles8(rfbClientPtr cl, int x, int y, int w, int h);
  30. static Bool sendHextiles16(rfbClientPtr cl, int x, int y, int w, int h);
  31. static Bool sendHextiles32(rfbClientPtr cl, int x, int y, int w, int h);
  32.  
  33.  
  34. /*
  35.  * rfbSendRectEncodingHextile - send a rectangle using hextile encoding.
  36.  */
  37.  
  38. Bool
  39. rfbSendRectEncodingHextile(cl, x, y, w, h)
  40.     rfbClientPtr cl;
  41.     int x, y, w, h;
  42. {
  43.     rfbFramebufferUpdateRectHeader rect;
  44.  
  45.     if (ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
  46.     if (!rfbSendUpdateBuf(cl))
  47.         return FALSE;
  48.     }
  49.  
  50.     rect.r.x = Swap16IfLE(x);
  51.     rect.r.y = Swap16IfLE(y);
  52.     rect.r.w = Swap16IfLE(w);
  53.     rect.r.h = Swap16IfLE(h);
  54.     rect.encoding = Swap32IfLE(rfbEncodingHextile);
  55.  
  56.     memcpy(&updateBuf[ublen], (char *)&rect,
  57.        sz_rfbFramebufferUpdateRectHeader);
  58.     ublen += sz_rfbFramebufferUpdateRectHeader;
  59.  
  60.     cl->rfbRectanglesSent[rfbEncodingHextile]++;
  61.     cl->rfbBytesSent[rfbEncodingHextile] += sz_rfbFramebufferUpdateRectHeader;
  62.  
  63.     switch (cl->format.bitsPerPixel) {
  64.     case 8:
  65.     return sendHextiles8(cl, x, y, w, h);
  66.     case 16:
  67.     return sendHextiles16(cl, x, y, w, h);
  68.     case 32:
  69.     return sendHextiles32(cl, x, y, w, h);
  70.     }
  71.  
  72.     rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel);
  73.     return FALSE;
  74. }
  75.  
  76.  
  77. #define PUT_PIXEL8(pix) (updateBuf[ublen++] = (pix))
  78.  
  79. #define PUT_PIXEL16(pix) (updateBuf[ublen++] = ((char*)&(pix))[0], \
  80.               updateBuf[ublen++] = ((char*)&(pix))[1])
  81.  
  82. #define PUT_PIXEL32(pix) (updateBuf[ublen++] = ((char*)&(pix))[0], \
  83.               updateBuf[ublen++] = ((char*)&(pix))[1], \
  84.               updateBuf[ublen++] = ((char*)&(pix))[2], \
  85.               updateBuf[ublen++] = ((char*)&(pix))[3])
  86.  
  87.  
  88. #define DEFINE_SEND_HEXTILES(bpp)                          \
  89.                                           \
  90.                                           \
  91. static Bool subrectEncode##bpp(CARD##bpp *data, int w, int h, CARD##bpp bg,   \
  92.                    CARD##bpp fg, Bool mono);              \
  93. static void testColours##bpp(CARD##bpp *data, int size, Bool *mono,          \
  94.                  Bool *solid, CARD##bpp *bg, CARD##bpp *fg);      \
  95.                                           \
  96.                                           \
  97. /*                                          \
  98.  * rfbSendHextiles                                  \
  99.  */                                          \
  100.                                           \
  101. static Bool                                      \
  102. sendHextiles##bpp(cl, rx, ry, rw, rh)                          \
  103.     rfbClientPtr cl;                                  \
  104.     int rx, ry, rw, rh;                                  \
  105. {                                          \
  106.     int x, y, w, h;                                  \
  107.     int startUblen;                                  \
  108.     char *fbptr;                                  \
  109.     CARD##bpp bg, fg, newBg, newFg;                          \
  110.     Bool mono, solid;                                  \
  111.     Bool validBg = FALSE;                              \
  112.     Bool validFg = FALSE;                              \
  113.     CARD##bpp clientPixelData[16*16*(bpp/8)];                      \
  114.                                           \
  115.     for (y = ry; y < ry+rh; y += 16) {                          \
  116.     for (x = rx; x < rx+rw; x += 16) {                      \
  117.         w = h = 16;                                  \
  118.         if (rx+rw - x < 16)                              \
  119.         w = rx+rw - x;                              \
  120.         if (ry+rh - y < 16)                              \
  121.         h = ry+rh - y;                              \
  122.                                           \
  123.         if ((ublen + 1 + (2 + 16 * 16) * (bpp/8)) > UPDATE_BUF_SIZE) {    \
  124.         if (!rfbSendUpdateBuf(cl))                      \
  125.             return FALSE;                          \
  126.         }                                      \
  127.                                           \
  128.         fbptr = (rfbScreen.pfbMemory + (rfbScreen.paddedWidthInBytes * y) \
  129.              + (x * (rfbScreen.bitsPerPixel / 8)));              \
  130.                                           \
  131.         (*cl->translateFn)(cl->translateLookupTable, &rfbServerFormat,    \
  132.                    &cl->format, fbptr, (char *)clientPixelData,   \
  133.                    rfbScreen.paddedWidthInBytes, w, h);          \
  134.                                           \
  135.         startUblen = ublen;                              \
  136.         updateBuf[startUblen] = 0;                          \
  137.         ublen++;                                  \
  138.                                           \
  139.         testColours##bpp(clientPixelData, w * h,                  \
  140.                  &mono, &solid, &newBg, &newFg);              \
  141.                                           \
  142.         if (!validBg || (newBg != bg)) {                      \
  143.         validBg = TRUE;                              \
  144.         bg = newBg;                              \
  145.         updateBuf[startUblen] |= rfbHextileBackgroundSpecified;          \
  146.         PUT_PIXEL##bpp(bg);                          \
  147.         }                                      \
  148.                                           \
  149.         if (solid) {                              \
  150.         cl->rfbBytesSent[rfbEncodingHextile] += ublen - startUblen;   \
  151.         continue;                              \
  152.         }                                      \
  153.                                           \
  154.         updateBuf[startUblen] |= rfbHextileAnySubrects;              \
  155.                                           \
  156.         if (mono) {                                  \
  157.         if (!validFg || (newFg != fg)) {                  \
  158.             validFg = TRUE;                          \
  159.             fg = newFg;                              \
  160.             updateBuf[startUblen] |= rfbHextileForegroundSpecified;   \
  161.             PUT_PIXEL##bpp(fg);                          \
  162.         }                                  \
  163.         } else {                                  \
  164.         validFg = FALSE;                          \
  165.         updateBuf[startUblen] |= rfbHextileSubrectsColoured;          \
  166.         }                                      \
  167.                                           \
  168.         if (!subrectEncode##bpp(clientPixelData, w, h, bg, fg, mono)) {   \
  169.         /* encoding was too large, use raw */                  \
  170.         validBg = FALSE;                          \
  171.         validFg = FALSE;                          \
  172.         ublen = startUblen;                          \
  173.         updateBuf[ublen++] = rfbHextileRaw;                  \
  174.         (*cl->translateFn)(cl->translateLookupTable,              \
  175.                    &rfbServerFormat, &cl->format, fbptr,      \
  176.                    (char *)clientPixelData,              \
  177.                    rfbScreen.paddedWidthInBytes, w, h);          \
  178.                                           \
  179.         memcpy(&updateBuf[ublen], (char *)clientPixelData,          \
  180.                w * h * (bpp/8));                      \
  181.                                           \
  182.         ublen += w * h * (bpp/8);                      \
  183.         }                                      \
  184.                                           \
  185.         cl->rfbBytesSent[rfbEncodingHextile] += ublen - startUblen;          \
  186.     }                                      \
  187.     }                                          \
  188.                                           \
  189.     return TRUE;                                  \
  190. }                                          \
  191.                                           \
  192.                                           \
  193. static Bool                                      \
  194. subrectEncode##bpp(CARD##bpp *data, int w, int h, CARD##bpp bg,              \
  195.            CARD##bpp fg, Bool mono)                      \
  196. {                                          \
  197.     CARD##bpp cl;                                  \
  198.     int x,y;                                      \
  199.     int i,j;                                      \
  200.     int hx=0,hy,vx=0,vy;                              \
  201.     int hyflag;                                      \
  202.     CARD##bpp *seg;                                  \
  203.     CARD##bpp *line;                                  \
  204.     int hw,hh,vw,vh;                                  \
  205.     int thex,they,thew,theh;                              \
  206.     int numsubs = 0;                                  \
  207.     int newLen;                                      \
  208.     int nSubrectsUblen;                                  \
  209.                                           \
  210.     nSubrectsUblen = ublen;                              \
  211.     ublen++;                                      \
  212.                                           \
  213.     for (y=0; y<h; y++) {                              \
  214.     line = data+(y*w);                              \
  215.     for (x=0; x<w; x++) {                              \
  216.         if (line[x] != bg) {                          \
  217.         cl = line[x];                              \
  218.         hy = y-1;                              \
  219.         hyflag = 1;                              \
  220.         for (j=y; j<h; j++) {                          \
  221.             seg = data+(j*w);                          \
  222.             if (seg[x] != cl) {break;}                      \
  223.             i = x;                              \
  224.             while ((seg[i] == cl) && (i < w)) i += 1;              \
  225.             i -= 1;                              \
  226.             if (j == y) vx = hx = i;                      \
  227.             if (i < vx) vx = i;                          \
  228.             if ((hyflag > 0) && (i >= hx)) {                  \
  229.             hy += 1;                          \
  230.             } else {                              \
  231.             hyflag = 0;                          \
  232.             }                                  \
  233.         }                                  \
  234.         vy = j-1;                              \
  235.                                           \
  236.         /* We now have two possible subrects: (x,y,hx,hy) and          \
  237.          * (x,y,vx,vy).  We'll choose the bigger of the two.          \
  238.          */                                  \
  239.         hw = hx-x+1;                              \
  240.         hh = hy-y+1;                              \
  241.         vw = vx-x+1;                              \
  242.         vh = vy-y+1;                              \
  243.                                           \
  244.         thex = x;                              \
  245.         they = y;                              \
  246.                                           \
  247.         if ((hw*hh) > (vw*vh)) {                      \
  248.             thew = hw;                              \
  249.             theh = hh;                              \
  250.         } else {                              \
  251.             thew = vw;                              \
  252.             theh = vh;                              \
  253.         }                                  \
  254.                                           \
  255.         if (mono) {                              \
  256.             newLen = ublen - nSubrectsUblen + 2;              \
  257.         } else {                              \
  258.             newLen = ublen - nSubrectsUblen + bpp/8 + 2;          \
  259.         }                                  \
  260.                                           \
  261.         if (newLen > (w * h * (bpp/8)))                      \
  262.             return FALSE;                          \
  263.                                           \
  264.         numsubs += 1;                              \
  265.                                           \
  266.         if (!mono) PUT_PIXEL##bpp(cl);                      \
  267.                                           \
  268.         updateBuf[ublen++] = rfbHextilePackXY(thex,they);          \
  269.         updateBuf[ublen++] = rfbHextilePackWH(thew,theh);          \
  270.                                           \
  271.         /*                                  \
  272.          * Now mark the subrect as done.                  \
  273.          */                                  \
  274.         for (j=they; j < (they+theh); j++) {                  \
  275.             for (i=thex; i < (thex+thew); i++) {              \
  276.             data[j*w+i] = bg;                      \
  277.             }                                  \
  278.         }                                  \
  279.         }                                      \
  280.     }                                      \
  281.     }                                          \
  282.                                           \
  283.     updateBuf[nSubrectsUblen] = numsubs;                      \
  284.                                           \
  285.     return TRUE;                                  \
  286. }                                          \
  287.                                           \
  288.                                           \
  289. /*                                          \
  290.  * testColours() tests if there are one (solid), two (mono) or more          \
  291.  * colours in a tile and gets a reasonable guess at the best background          \
  292.  * pixel, and the foreground pixel for mono.                      \
  293.  */                                          \
  294.                                           \
  295. static void                                      \
  296. testColours##bpp(data,size,mono,solid,bg,fg)                      \
  297.     CARD##bpp *data;                                  \
  298.     int size;                                      \
  299.     Bool *mono;                                      \
  300.     Bool *solid;                                  \
  301.     CARD##bpp *bg;                                  \
  302.     CARD##bpp *fg;                                  \
  303. {                                          \
  304.     CARD##bpp colour1, colour2;                              \
  305.     int n1 = 0, n2 = 0;                                  \
  306.     *mono = TRUE;                                  \
  307.     *solid = TRUE;                                  \
  308.                                           \
  309.     for (; size > 0; size--, data++) {                          \
  310.                                           \
  311.     if (n1 == 0)                                  \
  312.         colour1 = *data;                              \
  313.                                           \
  314.     if (*data == colour1) {                              \
  315.         n1++;                                  \
  316.         continue;                                  \
  317.     }                                      \
  318.                                           \
  319.     if (n2 == 0) {                                  \
  320.         *solid = FALSE;                              \
  321.         colour2 = *data;                              \
  322.     }                                      \
  323.                                           \
  324.     if (*data == colour2) {                              \
  325.         n2++;                                  \
  326.         continue;                                  \
  327.     }                                      \
  328.                                           \
  329.     *mono = FALSE;                                  \
  330.     break;                                      \
  331.     }                                          \
  332.                                           \
  333.     if (n1 > n2) {                                  \
  334.     *bg = colour1;                                  \
  335.     *fg = colour2;                                  \
  336.     } else {                                      \
  337.     *bg = colour2;                                  \
  338.     *fg = colour1;                                  \
  339.     }                                          \
  340. }
  341.  
  342. DEFINE_SEND_HEXTILES(8)
  343. DEFINE_SEND_HEXTILES(16)
  344. DEFINE_SEND_HEXTILES(32)
  345.